package com.lancoo.ccas53.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.*;
import com.lancoo.ccas53.exception.BizException;
import com.lancoo.ccas53.mapper.SplitClassMapper;
import com.lancoo.ccas53.mapper.TeachingClassStudentMapper;
import com.lancoo.ccas53.mapper.TeachingClassWeekMapper;
import com.lancoo.ccas53.pojo.common.PageInfo;
import com.lancoo.ccas53.pojo.vo.SplitTeachingClassDto;
import com.lancoo.ccas53.service.*;
import com.lancoo.ccas53.util.BatchInsert;
import com.lancoo.ccas53.util.PagingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @Author: mabolin
 * @Date: 2024-10-12-11:05
 * @Description:
 */
@Service
@Slf4j
public class SplitClassServiceImpl extends ServiceImpl<SplitClassMapper, SplitClass> implements SplitClassService {
    @Resource
    private CourseService courseService;
    @Resource
    private StudentService studentService;
    @Resource
    private TeachingClassStudentService teachingClassStudentService;
    @Resource
    private TeachingClassService teachingClassService;
    @Resource
    private MajorGradeService majorGradeService;
    @Resource
    private TeachingClassServiceImpl classImplService;
    @Resource
    private TeachingClassWeekMapper teachingClassWeekMapper;
    @Resource
    private TeachingClassStudentMapper teachingClassStudentMapper;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;
    @Resource
    private TeacherService teacherService;
    @Resource
    private TeachingClassTeacherService teachingClassTeacherService;

    @Override
    public Boolean removeSplitClass(List<String> uniqueShiftSigns) {
        //删除拆班数据
        this.lambdaUpdate().in(SplitClass::getSplitClassUuid, uniqueShiftSigns).remove();
        //删除拆班教学班
        List<Long> teachingClassIds = teachingClassService.lambdaQuery().in(TeachingClass::getSplitClassUuid, uniqueShiftSigns).list()
                .stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        teachingClassService.deleteClass(teachingClassIds);
        return true;
    }

    @Override
    public PageInfo<SplitClass> getSplitClassList(Integer currentPage, Integer pageSize, Integer taskId, String keyword) {
        Page<SplitClass> page = new Page<>(currentPage, pageSize);
        Page<SplitClass> splitClassPage = this.lambdaQuery().eq(SplitClass::getTaskId, taskId)
                .like(StringUtils.isNotBlank(keyword), SplitClass::getSplitName, keyword).page(page);
        //教学班
        List<TeachingClass> teachingClassList = teachingClassService.lambdaQuery().eq(TeachingClass::getTaskId, taskId).list();
        List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.lambdaQuery().in(ObjUtil.isNotEmpty(teachingClassList), TeachingClassWeek::getTeachingClassId,
                teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList())).list();
        List<TeachingClassTeacher> teachingClassTeacherList = teachingClassTeacherService.lambdaQuery().in(ObjUtil.isNotEmpty(teachingClassList), TeachingClassTeacher::getTeachingClassId,
                teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList())).list();
        List<Teacher> teacherList = teacherService.lambdaQuery().eq(Teacher::getTaskId, taskId).list();
        for (SplitClass splitClass : splitClassPage.getRecords()) {
            String uniqueShiftSign = splitClass.getSplitClassUuid();
            //拆班对应教学班
            List<TeachingClass> teachingClasses = teachingClassList.stream().filter(a -> a.getSplitClassUuid() != null && a.getSplitClassUuid().equals(uniqueShiftSign)).collect(Collectors.toList());
            teachingClasses.forEach(o -> {
                List<TeachingClassWeek> weekList = teachingClassWeekList.stream().filter(a -> a.getTeachingClassId().equals(o.getTeachingClassId())).collect(Collectors.toList());
                o.setTeachingClassWeeks(weekList);
                List<TeachingClassTeacher> teachingClassTeachers = teachingClassTeacherList.stream().filter(a -> a.getTeachingClassId().equals(o.getTeachingClassId())).collect(Collectors.toList());
                for (TeachingClassTeacher item : teachingClassTeachers) {
                    Teacher teacher = teacherList.stream().filter(a -> a.getTeacherId().equals(item.getTeacherId())).findFirst().get();
                    item.setIdentity(teacher.getIdentity())
                            .setImageUrl(teacher.getImageUrl())
                            .setTeacherName(teacher.getTeacherName())
                            .setBaseTeacherId(teacher.getBaseTeacherId());
                    switch (item.getHourType()) {
                        case 1:
                            item.setHourTypeName("讲授");
                            break;
                        case 2:
                            item.setHourTypeName("实验");
                            break;
                        case 3:
                            item.setHourTypeName("上机");
                            break;
                        case 4:
                            item.setHourTypeName("其他");
                            break;
                        default:
                            break;
                    }
                }
                o.setTeachingClassTeachers(teachingClassTeachers);
            });

            List<SplitTeachingClassDto> teachingClassDtoList = new ArrayList<>();
            if (CollUtil.isNotEmpty(teachingClasses)) {
                List<Long> courseIds = teachingClasses.stream().map(TeachingClass::getCourseId).distinct().collect(Collectors.toList());
                for (Long courseId : courseIds) {
                    SplitTeachingClassDto view = new SplitTeachingClassDto();
                    view.setCourseId(courseId);
                    view.setCourseName(teachingClasses.stream().filter(a -> a.getCourseId().equals(courseId)).findFirst().get().getCourseName());
                    List<TeachingClass> list = teachingClasses.stream().filter(a -> a.getCourseId().equals(courseId)).collect(Collectors.toList());
                    view.setTeachingClassList(list);
                    teachingClassDtoList.add(view);
                }
            }
            splitClass.setTeachingClassList(teachingClassDtoList);
        }
        return PagingUtil.formatPageResult(splitClassPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TeachingClass> addSplitClassList(Integer taskId, String classId, String uniqueShiftSign, List<Long> courseIds) {
        if (StringUtils.isNotBlank(uniqueShiftSign)) {
            //编辑-修改，先删除原来生成的教学班
            teachingClassService.lambdaUpdate().eq(TeachingClass::getSplitClassUuid, uniqueShiftSign).remove();
        }
        List<Course> courseList = courseService.lambdaQuery().eq(Course::getTaskId, taskId).in(Course::getCourseId, courseIds).list();
        List<Student> studentList = studentService.lambdaQuery().eq(Student::getClassId, classId).eq(Student::getTaskId, taskId).list();
        List<Long> studentIdCollect = studentList.stream().map(Student::getStudentId).collect(Collectors.toList());
        //分组上课的教学班生成后，原来生成的教学班信息将自动删除掉
        teachingClassStudentService.lambdaUpdate().in(TeachingClassStudent::getCourseId, courseIds)
                .in(TeachingClassStudent::getStudentId, studentIdCollect).remove();
        List<Long> teachingClassIds = teachingClassStudentService.lambdaQuery().in(TeachingClassStudent::getCourseId, courseIds).list()
                .stream().map(TeachingClassStudent::getTeachingClassId).collect(Collectors.toList());
        List<Long> needDeleteIds = teachingClassService.lambdaQuery().notIn(CollUtil.isNotEmpty(teachingClassIds), TeachingClass::getTeachingClassId, teachingClassIds)
                .in(TeachingClass::getCourseId, courseIds).list()
                .stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        teachingClassService.deleteClass(needDeleteIds);
        //单双班学生
        List<Student> singleStu = new ArrayList<>();
        List<Student> doubleStu = new ArrayList<>();
        studentList.forEach(stu -> {
            int last = Integer.parseInt(stu.getBaseStudentId().substring(stu.getBaseStudentId().length() - 1));
            if (last % 2 == 0) {
                doubleStu.add(stu);
            } else {
                singleStu.add(stu);
            }
        });
        Student student = studentList.get(0);
        MajorGrade majorGrade = majorGradeService.lambdaQuery().eq(MajorGrade::getGradeId, student.getGradeId())
                .eq(MajorGrade::getMajorName, student.getMajorName())
                .eq(MajorGrade::getBaseCollegeId, student.getBaseCollegeId())
                .eq(MajorGrade::getTaskId, taskId).one();
        if (majorGrade == null) {
            throw new BizException(student.getCollegeName() + "不存在" + student.getGradeName() + student.getMajorName() + "，请前往基础教务核实");
        }
        List<TeachingClass> classList = new ArrayList<>();
        //教学班对应学生
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        UUID uuid = UUID.randomUUID();
        for (Course course : courseList) {
            TeachingClass singleClass = new TeachingClass()
                    .setTaskId(taskId)
                    .setTeachingClassName(student.getClassName() + course.getCourseName() + "(单)")
                    .setCourseId(course.getCourseId())
                    .setCourseName(course.getCourseName())
                    .setStudyNature(course.getCourseNature())
                    .setMajorProp(course.getMajorProp())
                    .setClassNum(studentList.size() / 2)
                    .setBaseMajorId(student.getMajorId())
                    .setToClass(student.getClassId())
                    .setMajorName(student.getMajorName())
                    .setBaseCollegeId(student.getBaseCollegeId())
                    .setCollegeName(student.getCollegeName())
                    .setGradeId(student.getGradeId())
                    .setGradeName(student.getGradeName())
                    .setTeachingClassType(0)
                    .setFlag(1)
                    .setCampusId(majorGrade.getCampusId())
                    .setCampusName(majorGrade.getCampusName())
                    .setSplitClassUuid(uuid.toString())
                    .setIsSingle(1);
            teachingClassService.save(singleClass);
            classList.add(singleClass);
            //单班教学班学生
            singleStu.forEach(a -> {
                teachingClassStudentList.add(new TeachingClassStudent()
                        .setFlag(1)
                        .setTeachingClassId(singleClass.getTeachingClassId())
                        .setCourseId(course.getCourseId())
                        .setStudentId(a.getStudentId()));
            });

            TeachingClass doubleClass = new TeachingClass()
                    .setTaskId(taskId)
                    .setTeachingClassName(student.getClassName() + course.getCourseName() + "(双)")
                    .setCourseId(course.getCourseId())
                    .setCourseName(course.getCourseName())
                    .setCourseName(course.getCourseName())
                    .setStudyNature(course.getCourseNature())
                    .setClassNum(studentList.size() / 2)
                    .setBaseMajorId(student.getMajorId())
                    .setToClass(student.getClassId())
                    .setMajorName(student.getMajorName())
                    .setBaseCollegeId(student.getBaseCollegeId())
                    .setCollegeName(student.getCollegeName())
                    .setGradeId(student.getGradeId())
                    .setGradeName(student.getGradeName())
                    .setTeachingClassType(0)
                    .setFlag(1)
                    .setCampusId(majorGrade.getCampusId())
                    .setCampusName(majorGrade.getCampusName())
                    .setSplitClassUuid(uuid.toString())
                    .setIsSingle(2);
            teachingClassService.save(doubleClass);
            classList.add(doubleClass);
            //双班教学班学生
            doubleStu.forEach(a -> {
                teachingClassStudentList.add(new TeachingClassStudent()
                        .setFlag(1)
                        .setTeachingClassId(doubleClass.getTeachingClassId())
                        .setCourseId(course.getCourseId())
                        .setStudentId(a.getStudentId()));
            });
        }
        courseList.forEach(course -> {
            course.setTeachingSet(1);
        });
        courseService.updateBatchById(courseList);
        //教学班参数
        List<TeachingClassWeek> allTeachingClassWeeks = classImplService.initTeachingClassWeek(classList);
        Consumer<List<TeachingClassWeek>> teachingClassWeekConsumer = o -> teachingClassWeekMapper.addBatch(o);
        BatchInsert.batchSplitInsert(allTeachingClassWeeks, teachingClassWeekConsumer);
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        return classList;
    }

    @Override
    public List<TeachingClass> getSplitTeachingClass(String uniqueShiftSign) {
        List<TeachingClass> teachingClassList = teachingClassService.lambdaQuery()
                .eq(TeachingClass::getSplitClassUuid, uniqueShiftSign).list();
        List<Long> ids = teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        //填充教师
        List<Teacher> teachers = teacherService.lambdaQuery().list();
        Map<Long, List<TeachingClassTeacher>> teacherMap = teachingClassTeacherService.lambdaQuery()
                .in(TeachingClassTeacher::getTeachingClassId, ids).list()
                .stream().collect(Collectors.groupingBy(TeachingClassTeacher::getTeachingClassId));
        //填充参数
        Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekService.lambdaQuery()
                .in(TeachingClassWeek::getTeachingClassId, ids).list()
                .stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
        for (TeachingClass teachingClass : teachingClassList) {
            teachingClass.setTeachingClassTeachers(teacherMap.get(teachingClass.getTeachingClassId()));
            teachingClass.setTeachingClassWeeks(weekMap.get(teachingClass.getTeachingClassId()));
            if (teachingClass.getTeachingClassTeachers() != null) {
                for (TeachingClassTeacher item : teachingClass.getTeachingClassTeachers()) {
                    try {
                        Teacher teacher = teachers.stream().filter(a -> a.getTeacherId().equals(item.getTeacherId())).findFirst().get();
                        item.setIdentity(teacher.getIdentity());
                        item.setTeacherName(teacher.getTeacherName());
                        item.setImageUrl(teacher.getImageUrl());
                        item.setBaseTeacherId(teacher.getBaseTeacherId());
                    } catch (Exception e) {
                        throw new BizException("教师信息不存在或被删除");
                    }
                }
            }
        }
        return teachingClassList;
    }
}
